Next: Math Functions, Previous: Rounding Operations, Up: Numbers [Contents][Index]
In a computer, an integer is represented as a binary number, a sequence of bits (digits which are either zero or one). A bitwise operation acts on the individual bits of such a sequence. For example, shifting moves the whole sequence left or right one or more places, reproducing the same pattern moved over.
The bitwise operations in Emacs Lisp apply only to integers.
lsh, which is an abbreviation for logical
shift, shifts the bits in integer1 to the
left count places, or to the right if
count is negative, bringing zeros into the vacated
bits. If count is negative, lsh
shifts zeros into the leftmost (most-significant) bit,
producing a positive result even if integer1 is
negative. Contrast this with ash, below.
Here are two examples of lsh, shifting a
pattern of bits one place to the left. We show only the
low-order eight bits of the binary pattern; the rest are all
zero.
(lsh 5 1)
⇒ 10
;; Decimal 5 becomes decimal 10.
00000101 ⇒ 00001010
(lsh 7 1)
⇒ 14
;; Decimal 7 becomes decimal 14.
00000111 ⇒ 00001110
As the examples illustrate, shifting the pattern of bits one place to the left produces a number that is twice the value of the previous number.
Shifting a pattern of bits two places to the left produces results like this (with 8-bit binary numbers):
(lsh 3 2)
⇒ 12
;; Decimal 3 becomes decimal 12.
00000011 ⇒ 00001100
On the other hand, shifting one place to the right looks like this:
(lsh 6 -1)
⇒ 3
;; Decimal 6 becomes decimal 3.
00000110 ⇒ 00000011
(lsh 5 -1)
⇒ 2
;; Decimal 5 becomes decimal 2.
00000101 ⇒ 00000010
As the example illustrates, shifting one place to the right divides the value of a positive integer by two, rounding downward.
The function lsh, like all Emacs Lisp
arithmetic functions, does not check for overflow, so
shifting left can discard significant bits and change the
sign of the number. For example, left shifting 536,870,911
produces −2 in the 30-bit
implementation:
(lsh 536870911 1) ; left shift
⇒ -2
In binary, the argument looks like this:
;; Decimal 536,870,911
0111...111111 (30 bits total)
which becomes the following when left shifted:
;; Decimal −2
1111...111110 (30 bits total)
ash (arithmetic shift) shifts the
bits in integer1 to the left count
places, or to the right if count is negative.
ash gives the same results as
lsh except when integer1 and
count are both negative. In that case,
ash puts ones in the empty bit positions on the
left, while lsh puts zeros in those bit
positions.
Thus, with ash, shifting the pattern of bits
one place to the right looks like this:
(ash -6 -1) ⇒ -3
;; Decimal −6 becomes decimal −3.
1111...111010 (30 bits total)
⇒
1111...111101 (30 bits total)
In contrast, shifting the pattern of bits one place to the
right with lsh looks like this:
(lsh -6 -1) ⇒ 536870909
;; Decimal −6 becomes decimal 536,870,909.
1111...111010 (30 bits total)
⇒
0111...111101 (30 bits total)
Here are other examples:
; 30-bit binary values
(lsh 5 2) ; 5 = 0000...000101
⇒ 20 ; = 0000...010100
(ash 5 2)
⇒ 20
(lsh -5 2) ; -5 = 1111...111011
⇒ -20 ; = 1111...101100
(ash -5 2)
⇒ -20
(lsh 5 -2) ; 5 = 0000...000101 ⇒ 1 ; = 0000...000001
(ash 5 -2)
⇒ 1
(lsh -5 -2) ; -5 = 1111...111011 ⇒ 268435454 ; = 0011...111110
(ash -5 -2) ; -5 = 1111...111011 ⇒ -2 ; = 1111...111110
This function returns the bitwise AND of the arguments: the nth bit is 1 in the result if, and only if, the nth bit is 1 in all the arguments.
For example, using 4-bit binary numbers, the bitwise AND of 13 and 12 is 12: 1101 combined with 1100 produces 1100. In both the binary numbers, the leftmost two bits are both 1 so the leftmost two bits of the returned value are both 1. However, for the rightmost two bits, each is 0 in at least one of the arguments, so the rightmost two bits of the returned value are both 0.
Therefore,
(logand 13 12)
⇒ 12
If logand is not passed any argument, it
returns a value of −1. This number is an
identity element for logand because its binary
representation consists entirely of ones. If
logand is passed just one argument, it returns
that argument.
; 30-bit binary values
(logand 14 13) ; 14 = 0000...001110
; 13 = 0000...001101
⇒ 12 ; 12 = 0000...001100
(logand 14 13 4) ; 14 = 0000...001110 ; 13 = 0000...001101 ; 4 = 0000...000100 ⇒ 4 ; 4 = 0000...000100
(logand)
⇒ -1 ; -1 = 1111...111111
This function returns the bitwise inclusive OR of its
arguments: the nth bit is 1 in the result if, and
only if, the nth bit is 1 in at least one of the
arguments. If there are no arguments, the result is 0, which
is an identity element for this operation. If
logior is passed just one argument, it returns
that argument.
; 30-bit binary values
(logior 12 5) ; 12 = 0000...001100
; 5 = 0000...000101
⇒ 13 ; 13 = 0000...001101
(logior 12 5 7) ; 12 = 0000...001100 ; 5 = 0000...000101 ; 7 = 0000...000111 ⇒ 15 ; 15 = 0000...001111
This function returns the bitwise exclusive OR of its
arguments: the nth bit is 1 in the result if, and
only if, the nth bit is 1 in an odd number of the
arguments. If there are no arguments, the result is 0, which
is an identity element for this operation. If
logxor is passed just one argument, it returns
that argument.
; 30-bit binary values
(logxor 12 5) ; 12 = 0000...001100
; 5 = 0000...000101
⇒ 9 ; 9 = 0000...001001
(logxor 12 5 7) ; 12 = 0000...001100 ; 5 = 0000...000101 ; 7 = 0000...000111 ⇒ 14 ; 14 = 0000...001110
This function returns the bitwise complement of its argument: the nth bit is one in the result if, and only if, the nth bit is zero in integer, and vice-versa.
(lognot 5)
⇒ -6
;; 5 = 0000...000101 (30 bits total)
;; becomes
;; -6 = 1111...111010 (30 bits total)
Next: Math Functions, Previous: Rounding Operations, Up: Numbers [Contents][Index]